package com.holly.unit.deform.service;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.holly.unit.core.pojo.dict.SimpleDict;
import com.holly.unit.core.util.StrKitUtil;
import com.holly.unit.deform.api.constants.DeformConstants;
import com.holly.unit.deform.api.enums.WidgetTypeEnum;
import com.holly.unit.deform.api.exception.DeformException;
import com.holly.unit.deform.api.exception.enums.DeformExceptionEnum;
import com.holly.unit.deform.api.pojo.base.DesignFormDTO;
import com.holly.unit.deform.api.pojo.base.DictModelDTO;
import com.holly.unit.deform.api.pojo.base.TranslateDataDTO;
import com.holly.unit.deform.api.util.SimpleDictToDictModelUtil;
import com.holly.unit.deform.api.util.UserOrDeptUtil;
import com.holly.unit.deform.entity.DesignForm;
import com.holly.unit.deform.entity.DesignFormData;
import com.holly.unit.deform.mapper.DeformBaseInfoMapper;
import com.holly.unit.deform.mapper.DeformDataMapper;
import com.holly.unit.deform.util.DeformUtil;
import com.holly.unit.dict.api.context.DictContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.util.*;

/**
 * 类描述:表单设计 业务类
 *
 * @author fxr
 * @version 1.0.0
 * @date 2022/4/5 11:01
 */
@Service
@Slf4j
public class DeformBaseInfoService extends ServiceImpl<DeformBaseInfoMapper, DesignForm> {

    @Autowired
    private DeformDataMapper deformDataMapper;

    @Transactional(rollbackFor = Exception.class)
    public void saveMain(DesignForm designForm) {
        // 表单类型默认为主表
        if (StrUtil.isEmptyIfStr(designForm.getDesformType())) {
            designForm.setDesformType(DeformConstants.DEFORM_TYPE_MV);
        }
        // 异步创建 ElasticSearch 索引
        DeformUtil.asyncCreateEsIndex(designForm.getDesformCode());
        int ans = this.baseMapper.insert(designForm);
        if (ans<0) {
            log.error(DeformExceptionEnum.DEFORM_ONE_TO_MANY_ERROR.getUserTip());
            throw new DeformException(DeformExceptionEnum.DEFORM_ONE_TO_MANY_ERROR);
        }
    }

    /***
     * 判断是否是字典类型，如果是就查询字典
     * @param designForm
     * @return
     */
    public DesignForm queryAllDictItem(DesignForm designForm) {
        String designJson = (String) designForm.getDesformDesignJson();
        if (StrUtil.isEmpty(designJson)) {
            return designForm;
        }

        JSONObject json = JSONObject.parseObject(designJson);
        JSONArray list = json.getJSONArray("list");
        for (int i = 0; i < list.size(); i++) {
            JSONObject item = list.getJSONObject(i);
            String type = item.getString("type");
            // 判断是否是 栅格布局 或 子表
            if ("grid".equals(type) || "sub-table-design".equals(type)) {
                JSONArray columns = item.getJSONArray("columns");
                for (int j = 0; j < columns.size(); j++) {
                    JSONArray columnList = columns.getJSONObject(j).getJSONArray("list");
                    for (int k = 0; k < columnList.size(); k++) {
                        this.ifCurrentIsSelect(columnList.getJSONObject(k));
                    }
                }
            } else {
                this.ifCurrentIsSelect(item);
            }
        }
        designForm.setDesformDesignJson(json.toJSONString());

        return designForm;
    }


    public Map<String, List<DictModelDTO>> translateColumns(List<TranslateDataDTO> translateDataList) {
        Map<String, List<DictModelDTO>> translateMap = new HashMap<>();
        // 待翻译的用户数据
        List<TranslateDataDTO> userTransDataList = new ArrayList<>();
        // 待翻译的部门数据
        List<TranslateDataDTO> departDataList = new ArrayList<>();
        for (TranslateDataDTO transItem : translateDataList) {
            // 判断翻译类型
            WidgetTypeEnum type = transItem.getType();
            String customReturnField = transItem.getCustomReturnField();
            if (type == WidgetTypeEnum.SELECT_USER) {
                // 翻译用户组件
                userTransDataList.add(transItem);
            } else if (type == WidgetTypeEnum.SELECT_DEPART) {
                // 翻译部门组件
                departDataList.add(transItem);
            }
        }
        // 查询并翻译出所有的用户信息
        if (userTransDataList.size() > 0) {
            QueryWrapper userQueryWrapper = this.getTranslateQueryWrapperByCustomReturnField(userTransDataList);
            // TODO 查询出所有的用户信息【需要验证】
            List<JSONObject> userQueryList = UserOrDeptUtil.queryAllUser();
            //List<JSONObject> userQueryList = sysBaseApi.queryAllUser(userQueryWrapper);
            this.packageOptionsPutTranslateMap(translateMap, userTransDataList, userQueryList, "realname");
        }
        // 查询并翻译出所有的部门信息
        if (departDataList.size() > 0) {
            QueryWrapper departQueryWrapper = this.getTranslateQueryWrapperByCustomReturnField(departDataList);
            // TODO 查询出所有的部门信息【需要验证】
            List<JSONObject> departQueryList = UserOrDeptUtil.queryAllDepart();
            //List<JSONObject> departQueryList = sysBaseApi.queryAllDepart(departQueryWrapper);
            this.packageOptionsPutTranslateMap(translateMap, departDataList, departQueryList, "departName");
        }
        return translateMap;
    }

    @Transactional(rollbackFor = Exception.class)
    public void updateMain(DesignForm designForm, List<DesignFormData> designFormDataList) {
        this.baseMapper.updateById(designForm);

        // 1.先删除子表数据
        deformDataMapper.deleteByMainId(designForm.getId());

        // 2.子表数据重新插入
        for (DesignFormData entity : designFormDataList) {
            // 外键设置
            entity.setDesformId(designForm.getId());
            deformDataMapper.insert(entity);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public void delMain(String id) {
        DesignForm designForm = baseMapper.selectById(id);
        if (designForm == null) {
            log.error(DeformExceptionEnum.DEFORM_QUERY_BY_ID_ERROR.getUserTip());
            throw new DeformException(DeformExceptionEnum.DEFORM_QUERY_BY_ID_ERROR,id);
        }
        if (designForm != null) {
            deformDataMapper.deleteByMainId(designForm.getId());
            this.baseMapper.deleteById(designForm.getId());
            // 异步删除 ElasticSearch 索引
            DeformUtil.asyncRemoveEsIndex(designForm.getDesformCode());
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public void delBatchMain(Collection<? extends Serializable> idList) {
        List<DesignForm> list = baseMapper.selectList(new LambdaQueryWrapper<DesignForm>().in(DesignForm::getId, idList));
        for (DesignForm designForm : list) {
            deformDataMapper.deleteByMainId(designForm.getId());
            this.baseMapper.deleteById(designForm.getId());
            // 异步删除 ElasticSearch 索引
            DeformUtil.asyncRemoveEsIndex(designForm.getDesformCode());
        }
    }

    public DesignForm getByCode(String desformCode) {
        LambdaQueryWrapper<DesignForm> queryWrapper = new LambdaQueryWrapper<DesignForm>();
        queryWrapper.eq(DesignForm::getDesformCode, desformCode);

        // 首先查询出表单配置json
        DesignForm designForm = baseMapper.selectOne(queryWrapper);
        return designForm;
    }


    public DesignForm getByCgformCode(String code){

        LambdaQueryWrapper<DesignForm> queryWrapper = new LambdaQueryWrapper<DesignForm>();
        queryWrapper.eq(DesignForm::getCgformCode, code);

        // 首先查询出表单配置json
        DesignForm designForm = baseMapper.selectOne(queryWrapper);
        return designForm;

    }



    /*************************************************工具方法***********************************************/

    /**
     * 根据不同的 CustomReturnField 生成不同的 QueryWrapper
     *
     * @param transDataList
     * @return
     */
    private QueryWrapper getTranslateQueryWrapperByCustomReturnField(List<TranslateDataDTO> transDataList) {
        QueryWrapper<?> queryWrapper = new QueryWrapper();
        Map<String, List<String>> inMap = new HashMap<>();
        for (TranslateDataDTO transItem : transDataList) {
            String customReturnField = transItem.getCustomReturnField();
            List<String> list = inMap.computeIfAbsent(customReturnField, k -> new ArrayList<>());
            list.addAll(transItem.getDataList());
        }
        for (String key : inMap.keySet()) {
            // 驼峰转下划线
            String inKey = StrKitUtil.camelToUnderline(key);
            queryWrapper.in(inKey, inMap.get(key)).or();
        }
        return queryWrapper;
    }

    /**
     * 将返回数据，包装成前台能识别的Options
     */
    private void packageOptionsPutTranslateMap(Map<String, List<DictModelDTO>> translateMap, List<TranslateDataDTO> translateDataList, List<JSONObject> queryDataList, String textLabel) {
        for (TranslateDataDTO transItem : translateDataList) {
            for (String data : transItem.getDataList()) {
                for (JSONObject queryData : queryDataList) {
                    String value = queryData.getString(transItem.getCustomReturnField());
                    if (value != null && value.equals(data)) {
                        String text = queryData.getString(textLabel);
                        List<DictModelDTO> list = translateMap.computeIfAbsent(transItem.getKey(), k -> new ArrayList<>());
                        list.add(new DictModelDTO(value, text));
                        break;
                    }
                }
            }
        }
    }

    /**
     * 判断当前项是否为select
     */
    private void ifCurrentIsSelect(JSONObject item) {
        String type = item.getString("type");
        if ("select".equals(type)) {
            JSONArray selectOptions = this.queryDictOptions(item);
            if (selectOptions != null) {
                JSONObject options = item.getJSONObject("options");
                options.put("remote", false);
                options.put("showLabel", true);
                options.put("options", selectOptions);
            }
        }
    }

    /**
     * 查询字典数据
     */
    private JSONArray queryDictOptions(JSONObject item) {
        try {
            JSONObject options = item.getJSONObject("options");
            String remote = options.getString("remote");
            // 判断是否为字典类型
            if ("dict".equals(remote)) {
                String dictCode = options.getString("dictCode");
                // 封装
                List<SimpleDict> simpleDicts = DictContext.me().getDictDetailsByDictTypeCode(dictCode);
                List<DictModelDTO> dictItems = SimpleDictToDictModelUtil.simpleDictToDictModel(simpleDicts);
                JSONArray selectOptions = new JSONArray();
                for (DictModelDTO dictModel : dictItems) {
                    JSONObject option = new JSONObject();
                    option.put("label", dictModel.getText());
                    option.put("value", dictModel.getValue());
                    selectOptions.add(option);
                }
                return selectOptions;

            }
        } catch (Exception e) {
            // do nothing
        }
        return null;
    }


    public boolean checkCode(DesignFormDTO dto) {
        LambdaQueryWrapper<DesignForm> queryWrapper = new LambdaQueryWrapper<DesignForm>();
        queryWrapper.eq(DesignForm::getDesformCode, dto.getDesformCode());
        if(StrUtil.isNotEmpty(dto.getId())){
            queryWrapper.ne(DesignForm::getId, dto.getId());
        }
        DesignForm designForm = baseMapper.selectOne(queryWrapper);
        if(designForm != null){
            return true;
        }
        return false;
    }
}
